﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.ComponentModel;

namespace Simulatore_0._1
{
    public class ModelloFS2
    {

        #region Variabili

        //Link a pannello principale
        private MainView vista;
        //Link a pannello XNA
        private Game1 game;

        public double nStepEspansione { get; private set; }
        public double nStepMaturita { get; private set; }
        public double nStepCrisi { get; private set; }
        public bool is_suspend { get; private set; }
        public int passo { get; private set; }
        public Random r { get; private set; }
        public double maxLeverageRnd = 10;
        public double maxRendimentoRnd = 10;
        public bool inizializzazione_terminata { get; private set; }

        //TAB IMPOSTAZIONE
        public int nStep { get; private set; }
        public double rendimentoRiskFree { get; private set; }
        public double rendimentoMercatoAttuale { get; private set; }
        public bool show_valori_dati { get; private set; }
        public int fase_espansione { get; private set; }
        public int fase_maturita { get; private set; }
        public int fase_crisi { get; private set; }
        public int dimRedHole { get; private set; }

        // TAB MODIFICABILI SOLO DA AMMINISTRATORE
        public double Rm_espansione { get; private set; }  //default value 6
        public double Rm_maturita { get; private set; }  //default value 4 
        public double Rm_crisi { get; private set; }     //default value 2

        //TAB LEADER
        public int nBancheLeader { get; private set; }
        public Banca[] leader { get; private set; }
        public double maxLeverageBankLeader { get; private set; }
        public double crescitaRendimentoMaxStepLeader { get; private set; }
        public double crescitaLevaMaxStepLeader { get; private set; }
        public int ritardo_leader_follower { get; private set; }
        public int ritardo_leader_locali { get; private set; }

        //TAB FOLLOWER
        public int nBancheFollower { get; private set; }
        public Banca[] follower { get; private set; }
        public double maxLeverageBankFollower { get; private set; }
        public double crescitaRendimentoMaxStepFollower { get; private set; }
        public double crescitaLevaMaxStepFollower { get; private set; }

        //TAB LOCALI

        public int nBancheLocali { get; private set; }
        public Banca[] locali { get; private set; }
        public double maxLeverageBankLocali { get; private set; }
        public double crescitaRendimentoMaxStepLocali { get; private set; }
        public double crescitaLevaMaxStepLocali { get; private set; }

        //TAB ORGANO DI GOVERNO
        public OrganoDiGoverno odg { get; private set; }
        public double maxLeverageOrganoDiGoverno { get; private set; }
        public bool check_organoGovernoActive { get; private set; }

        #endregion Variabili

        public ModelloFS2 ( MainView vista, Game1 game )
        {
            is_suspend=false;
            this.vista = vista;
            inizializzazione_terminata=false;
            this.game = game;
            r = new Random();

        }

        public void avviaSimulazione ( BackgroundWorker worker, DoWorkEventArgs e )
        {
            //istanzio i parametri del simulatore
            getParametriSimulatore();

            //inizializzo l'organo di governo
            odg = new OrganoDiGoverno(this, check_organoGovernoActive, maxLeverageOrganoDiGoverno);

            //inizializzo le Banche Leader
            leader = new Banca[nBancheLeader];
            for(int i = 0; i < leader.Length; i++)
                leader[i] = new Banca(this, odg, i, r.NextDouble() * maxRendimentoRnd, (r.NextDouble() * maxLeverageRnd), "Leader");

            //inizializzo le Banche Follower
            follower = new Banca[nBancheFollower];
            for(int i = 0; i < follower.Length; i++)
                follower[i] = new Banca(this, odg, i, r.NextDouble() * maxRendimentoRnd, (r.NextDouble() * maxLeverageRnd), "Follower");

            //inizializzo le Banche Locali
            locali = new Banca[nBancheLocali];
            for(int i = 0; i < locali.Length; i++)
                locali[i] = new Banca(this, odg, i, r.NextDouble() * maxRendimentoRnd, (r.NextDouble() * maxLeverageRnd), "Locali");

            inizializzazione_terminata=true;
            startSimulazione(worker, e);
        }

        //viene fatto partire in un thread
        public void startSimulazione ( System.ComponentModel.BackgroundWorker worker, DoWorkEventArgs e )
        {
            try
            {
                string desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                string fullFileName = Path.Combine(desktopFolder, "Risultati.txt");
                using(StreamWriter sw = new StreamWriter(fullFileName))
                {
                    sw.WriteLine("RISULTATI FILE");
                    sw.WriteLine();
                    sw.WriteLine("id\tTipo\t\tRendimento\tLeverage\n\n");
                    nStepEspansione = (Convert.ToDouble(nStep)/100*fase_espansione);
                    nStepMaturita = (Convert.ToDouble(nStep)/100*fase_maturita);
                    nStepCrisi = (Convert.ToDouble(nStep)/100*fase_crisi);
                    passo=1;
                    while(passo<=nStep)
                    {
                        Console.WriteLine("passo:----{0}", passo);
                        /*Ad ogni passo il RendimentoMercatoAttuale cresce in maniera lineare
                         *  LEGENDA
                         * 
                         *  TRA 1--> fase_espansione cresce da 1-->6
                         * 
                         * PROPORZIONE rendimentoMercatoAttuale : passo = 5 : nStepEspansione
                         * 
                         * Quindi rendimentoMercatoAttuale = {(passo*5) / nStepEspansione} +1
                         * 
                         * CON + 1 FACCIO traslare da 0-->5 a 1-->6
                         */

                        if(passo<=nStepEspansione)
                        {
                            Console.WriteLine("1---------6");

                            rendimentoMercatoAttuale=(Convert.ToDouble(passo*(Rm_espansione-1)) / nStepEspansione) + 1;
                        }
                        //TRA fase_espansione-->fase_espansione+fase_maturita decresce da 6-->4

                        /*  TRA fase_espansione-->fase_espansione+fase_maturita decresce 6-->4
                         * 
                         * PROPORZIONE rendimentoMercatoAttuale : (passo-nStepEspansione) = (-2) : nStepMaturita
                         * 
                         * Quindi rendimentoMercatoAttuale = {(passo-*5) / nStepEspansione} +6
                         * 
                         * CON + 6 FACCIO traslare da 0-->-2 a 6-->4
                         */

                        else if(passo > nStepEspansione && passo < nStepEspansione+nStepMaturita)
                        {
                            Console.WriteLine("6---------4");

                            rendimentoMercatoAttuale = ((Convert.ToDouble(passo) - nStepEspansione) * (Rm_maturita-Rm_espansione) / nStepMaturita) + Rm_espansione;

                        }

                         //TRA fase_espansione+faseMaturita-->fase_espansione+fase_maturita+faseCrisi decresce da 4-->2

                        /*  TRA fase_espansione+faseMaturita-->fase_espansione+fase_maturita+faseCrisi decresce 4-->2
                         * 
                         * PROPORZIONE rendimentoMercatoAttuale : (passo-(nStepEspansione+nStepMatuita)) = (-2) : nStepCrisi
                         * 
                         * Quindi rendimentoMercatoAttuale = {(passo-*5) / nStepEspansione} +4
                         * 
                         * CON + 4 FACCIO traslare da 0-->-2 a 4-->2
                         */


                        else if(passo>=nStepEspansione+nStepMaturita)
                        {
                            Console.WriteLine("4---------2");

                            rendimentoMercatoAttuale = ((Convert.ToDouble(passo) - nStepEspansione - nStepMaturita) * (Rm_crisi-Rm_maturita) / nStepCrisi) + Rm_maturita;
                        }
                        Console.WriteLine("rendmercAttuale++++++++{0}", rendimentoMercatoAttuale);

                        for(int j = 0; j < nBancheLeader; j++)
                        {
                            leader[j].behaviour_leader();
                            sw.WriteLine("{0}", leader[j].ToString());
                        }

                        if(passo>ritardo_leader_follower)
                        {
                            for(int j = 0; j < nBancheFollower; j++)
                            {
                                follower[j].behaviour_follower();
                                sw.WriteLine("{0}", follower[j].ToString());
                            }
                        }

                        if(passo>ritardo_leader_locali)
                        {
                            for(int j = 0; j < nBancheLocali; j++)
                            {
                                locali[j].behaviour_locali();
                                sw.WriteLine("{0}", locali[j].ToString());
                            }
                        }
                        if((worker.CancellationPending == true))
                        {
                            e.Cancel = true;
                            break;
                        }

                        while(is_suspend)
                            ;
                           
                        passo++;
                        worker.ReportProgress(Convert.ToInt32(((passo-1)*100)/nStep));
                    }

                    // MessageBox.Show("Simulazione terminata!", " ", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    sw.Close();
                }//end of STREAMWRITER
            }
            finally { }
        }

        public void SospendiCreazione ()
        {
            this.is_suspend=true;
        }

        public void ResumeEsecuzione ()
        {
            getParametriSimulatore();
            odg.check_organoGovernoActive=check_organoGovernoActive;
            odg.maxLeverageOrganoDiGoverno=maxLeverageOrganoDiGoverno;
            this.is_suspend=false;        
        }

        public void getParametriSimulatore ()
        {
            //TAB IMPOSTAZIONI
            this.nStep = Convert.ToInt32(vista.numStep.Text);
            Console.WriteLine("nstep {0}", nStep);
            this.rendimentoRiskFree = Convert.ToDouble(vista.textBoxIFreeRisk.Text);
            Console.WriteLine("iFreeRisk {0}", rendimentoRiskFree);
            this.show_valori_dati = Convert.ToBoolean(vista.checkBox1.Checked);
            Console.WriteLine("show_valori_dati {0}", show_valori_dati);
            this.fase_espansione = Convert.ToInt32(vista.textBox10.Text);
            Console.WriteLine("fase_espansione {0}", fase_espansione);
            this.fase_maturita = Convert.ToInt32(vista.textBox9.Text);
            Console.WriteLine("fase_maturita {0}", fase_maturita);
            this.fase_crisi = Convert.ToInt32(vista.textBox11.Text);
            Console.WriteLine("fase_crisi {0}", fase_crisi);

            int _dimRedHole=0;
            if(vista.trackBar4.InvokeRequired)
            {
                vista.trackBar4.Invoke(new MethodInvoker(delegate { _dimRedHole = vista.trackBar4.Value; }));
                this.dimRedHole=_dimRedHole;
            }
            else
                this.dimRedHole = vista.trackBar4.Value;

            Console.WriteLine("dimRedHole {0}", dimRedHole);

            this.ritardo_leader_follower = Convert.ToInt32(vista.textBox15.Text);
            Console.WriteLine("ritardo_leader_follower {0}", ritardo_leader_follower);
            this.ritardo_leader_locali = Convert.ToInt32(vista.textBox16.Text);
            Console.WriteLine("ritardo_leader_locali {0}", ritardo_leader_locali);

            //TAB LEADER
            this.nBancheLeader = Convert.ToInt32(vista.textBoxnBancheLeader.Text);
            Console.WriteLine("nbanchelear {0}", nBancheLeader);
            this.crescitaRendimentoMaxStepLeader = Convert.ToDouble(vista.textCrescitaLeader.Text);
            Console.WriteLine("crescitaRendimentoMaxStep {0}", crescitaRendimentoMaxStepLeader);
            this.crescitaLevaMaxStepLeader = Convert.ToDouble(vista.textCrescitaLevaLeader.Text);
            Console.WriteLine("crescitaLevaMaxStep {0}", crescitaLevaMaxStepLeader);

            int _maxLeverageBankLeader=0;
            if(vista.trackBarLeverageLeader.InvokeRequired)
            {
                vista.trackBarLeverageLeader.Invoke(new MethodInvoker(delegate { _maxLeverageBankLeader = vista.trackBarLeverageLeader.Value; }));
                this.maxLeverageBankLeader=_maxLeverageBankLeader;
            }
            else
                this.maxLeverageBankLeader = Convert.ToDouble(vista.trackBarLeverageLeader.Value);
            Console.WriteLine("leverageMaxBankLeader {0}", maxLeverageBankLeader);

            //TAB FOLLOWER
            this.nBancheFollower = Convert.ToInt32(vista.textBoxbf.Text);
            Console.WriteLine("nbanchelear {0}", nBancheFollower);
            this.crescitaRendimentoMaxStepFollower = Convert.ToDouble(vista.textBox2.Text);
            Console.WriteLine("crescitaRendimentoMaxStep {0}", crescitaRendimentoMaxStepFollower);
            this.crescitaLevaMaxStepFollower = Convert.ToDouble(vista.textBox1.Text);
            Console.WriteLine("crescitaLevaMaxStep {0}", crescitaLevaMaxStepFollower);
            int _maxLeverageBankFollower=0;
            if(vista.trackBar1.InvokeRequired)
            {
                vista.trackBar1.Invoke(new MethodInvoker(delegate { _maxLeverageBankFollower = vista.trackBar1.Value; }));
                this.maxLeverageBankFollower=_maxLeverageBankFollower;
            }
            else
                this.maxLeverageBankFollower = Convert.ToDouble(vista.trackBar1.Value);
            Console.WriteLine("leverageMaxBankFollower {0}", maxLeverageBankFollower);

            //TAB LOCALI
            this.nBancheLocali = Convert.ToInt32(vista.textBox8.Text);
            Console.WriteLine("nbanchelear {0}", nBancheLocali);
            this.crescitaRendimentoMaxStepLocali = Convert.ToDouble(vista.textBox6.Text);
            Console.WriteLine("crescitaRendimentoMaxStep {0}", crescitaRendimentoMaxStepLocali);
            this.crescitaLevaMaxStepLocali = Convert.ToDouble(vista.textBox5.Text);
            Console.WriteLine("crescitaLevaMaxStep {0}", crescitaLevaMaxStepLocali);

            int _maxLeverageBankLocali=0;
            if(vista.trackBar3.InvokeRequired)
            {
                vista.trackBar3.Invoke(new MethodInvoker(delegate { _maxLeverageBankLocali = vista.trackBar3.Value; }));
                this.maxLeverageBankLocali=_maxLeverageBankLocali;
            }
            else
                this.maxLeverageBankLocali = Convert.ToDouble(vista.trackBar3.Value);
            Console.WriteLine("leverageMaxBankLocali {0}", maxLeverageBankLocali);

            //TAB ORGANO DI GOVERNO
            this.check_organoGovernoActive = Convert.ToBoolean(vista.codg.Checked);
            Console.WriteLine("check_organoGovernoActive {0}", check_organoGovernoActive);

            int _maxLeverageBankOdG=0;
            if(vista.trackBar2.InvokeRequired)
            {
                vista.trackBar2.Invoke(new MethodInvoker(delegate { _maxLeverageBankOdG = vista.trackBar2.Value; }));
                this.maxLeverageOrganoDiGoverno=_maxLeverageBankOdG;
            }
            else
                this.maxLeverageOrganoDiGoverno = Convert.ToDouble(vista.trackBar2.Value);
            Console.WriteLine("maxLeverageOrganoDiGoverno {0}", maxLeverageOrganoDiGoverno);

            //INIZIALIZZO I VALORI Rm_espansione, Rm_maturita, Rm_crisi 
            // ==>MODIFICABILI SOLO DA ADMIN <==
            //Se non sono visibili vengono presi i valori di default
            if(vista.textBox14.Visible==true)
                this.Rm_espansione=Convert.ToInt32(vista.textBox14.Text);
            else
                this.Rm_espansione = 6;
            if(vista.textBox13.Visible==true)
                this.Rm_maturita=Convert.ToInt32(vista.textBox13.Text);
            else
                this.Rm_maturita = 4;
            if(vista.textBox4.Visible==true)
                this.Rm_crisi=Convert.ToInt32(vista.textBox4.Text);
            else
                this.Rm_crisi = 2;
        }
    }//end class

}//end namespace